package com.nd.android.musicboxlibrary.business.comm;

import com.nd.android.musicboxlibrary.util.Log;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketException;
import java.net.SocketTimeoutException;
import java.net.URI;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.zip.GZIPInputStream;

/**
 * <br>
 * Created 2014年9月16日 上午12:16:36
 * 
 * @author wat.ztag
 * @see
 */
public final class HttpTool_Base implements MagicNumber {

    /**
     * Creates a new instance of HttpTool_Base. <br>
     * Created 2014年9月16日 上午12:16:46
     */
    private HttpTool_Base() {
    }

    private static final int NET_WORK_NOT_ACTIVIE = 600;

    private static final String NET_WORK_NOT_ACTIVIE_DESC = "诶，是不是网络有问题。";

    private static final int NET_WORK_SOCKET_TIME_OUT = 480;

    private static final String NET_WORK_SOCKET_TIME_OUT_DESC = "连接超时";

    public static final String CONTENT_ENCODING = HTTP.UTF_8;

    public static final String CONTENT_TYPE_JSON = "application/json";

    private static final String FIELD_META = "meta";

    private static final String FIELD_DATA = "data";

    private static final String HTTP_STATUS_400 = "请求失败";

    private static final String HTTP_STATUS_401 = "需要认证";

    private static final String HTTP_STATUS_403 = "无权限";

    private static final String HTTP_STATUS_404 = "请求资源不存在";

    private static final String HTTP_STATUS_405 = "不支持的方法";

    private static final String HTTP_STATUS_406 = "请求不被接受";

    private static final String HTTP_STATUS_407 = "认证错误";

    private static final String HTTP_STATUS_408 = "认证过期";

    private static final String HTTP_STATUS_409 = "未名错误";

    /**
     * 执行get请求
     * 
     * @param requestUrl
     *            请求地址
     * @return String
     * @throws NdException Exception
     */
    public static String get(String requestUrl) throws NdException {
        return get(requestUrl, null, CONTENT_TYPE_JSON, CONTENT_ENCODING);
    }

    /**
     * 执行get请求
     * 
     * @param requestUrl
     *            请求地址
     * @param headerMap
     *            请求头
     * @return String
     * @throws NdException Exception
     */
    public static String get(String requestUrl, HashMap<String, String> headerMap)
            throws NdException {
        return get(requestUrl, headerMap, CONTENT_TYPE_JSON, CONTENT_ENCODING);
    }

    /**
     * 执行get请求
     * 
     * @param requestUrl
     *            请求地址
     * @param headerMap
     *            请求头
     * @param content_type
     *            内容类型
     * @param content_encoding
     *            内容编码
     * @return String
     * @throws NdException Exception
     */
    public static String get(String requestUrl, HashMap<String, String> headerMap,
            String content_type, String content_encoding) throws NdException {
        BufferedReader in = null;
        InputStream is;
        Log.d(requestUrl);
        try {
            HttpParams httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, n20000);
            HttpConnectionParams.setSoTimeout(httpParams, n60000);
            HttpClientParams.setRedirecting(httpParams, true);
            HttpClient client = new DefaultHttpClient(httpParams);
            HttpGet request = new HttpGet();
            request.setURI(new URI(requestUrl));
            if (headerMap != null) {
                for (String name : headerMap.keySet()) {
                    request.addHeader(name, headerMap.get(name));
                }
            }
            request.addHeader("Accept-Encoding", "gzip");
            HttpResponse response = client.execute(request);
            int responseCode = response.getStatusLine().getStatusCode();
            is = response.getEntity().getContent();
            for (Header header : response.getAllHeaders()) {
                String name = header.getName();
                String value = header.getValue();
                if (name.equals("Content-Encoding") && value.equals("gzip")) {
                    is = new GZIPInputStream(is);
                }
            }
            in = new BufferedReader(new InputStreamReader(is, content_encoding));
            StringBuffer sb = new StringBuffer("");
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            String strResponse = sb.toString();
            Log.d(responseCode + ": " + strResponse);
            JSONObject jsonResult = null;
            JSONObject jsonMeta = null;
            String strData = null;
            if (responseCode == HttpStatus.SC_OK) {
                // 状态码200，需判断是否有数据对象data
                try {
                    jsonResult = new JSONObject(strResponse);
                    if (jsonResult.has(FIELD_DATA)) {
                        strData = jsonResult.getString(FIELD_DATA);
                    }
                } catch (Exception e) {
                    Log.i(e.toString());
                }
                if (strData != null) {
                    strResponse = strData;
                }
            } else if (responseCode == HttpStatus.SC_UNAUTHORIZED) {
                jsonResult = new JSONObject(strResponse);
                jsonResult.put("code", HttpStatus.SC_UNAUTHORIZED);
                throw new NdException(jsonResult);
            } else {
                // 错误类型1、有meta
                try {
                    jsonResult = new JSONObject(strResponse);
                    if (jsonResult.has(FIELD_META)) {
                        jsonMeta = jsonResult.getJSONObject(FIELD_META);
                    }
                } catch (Exception e) {
                    Log.i(e.toString());
                }

                if (jsonMeta != null) {
                    throw new NdException(jsonMeta);
                }
                if (strResponse != null && strResponse.length() > 2) {
                    throw new NdException(responseCode, strResponse);
                } else {
                    throw new NdException(responseCode, getErrorMsg(responseCode));
                }
            }
            return strResponse;
        } catch (SocketException e) {
            throw new NdException(NET_WORK_NOT_ACTIVIE, NET_WORK_NOT_ACTIVIE_DESC);
        } catch (UnknownHostException e) {
            throw new NdException(NET_WORK_NOT_ACTIVIE, NET_WORK_NOT_ACTIVIE_DESC);
        } catch (SocketTimeoutException e) {
            throw new NdException(NET_WORK_SOCKET_TIME_OUT, NET_WORK_SOCKET_TIME_OUT_DESC);
        } catch (Exception e) {
            throw new NdException(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 执行post请求
     * 
     * @param requestUrl
     *            请求地址
     * @param params
     *            参数
     * @return String
     * @throws NdException Exception
     */
    public static String post(String requestUrl, JSONObject params) throws NdException {
        return post(requestUrl, params, null, CONTENT_TYPE_JSON, CONTENT_ENCODING);
    }

    /**
     * 执行post请求
     * 
     * @param requestUrl
     *            请求地址
     * @param params
     *            参数
     * @param headerMap
     *            请求头
     * @return String
     * @throws NdException Exception
     */
    public static String post(String requestUrl, JSONObject params,
            HashMap<String, String> headerMap) throws NdException {
        return post(requestUrl, params, headerMap, CONTENT_TYPE_JSON, CONTENT_ENCODING);
    }

    /**
     * 执行post请求
     * 
     * @param requestUrl
     *            请求地址
     * @param params
     *            参数
     * @param headerMap
     *            请求头
     * @param content_type
     *            内容类型
     * @param content_encoding
     *            内容编码
     * @return String
     * @throws NdException Exception
     */
    public static String post(String requestUrl, JSONObject params,
            HashMap<String, String> headerMap, String content_type, String content_encoding)
            throws NdException {
        return post(requestUrl, params == null ? null : params.toString(), headerMap, content_type,
                content_encoding);
    }

    /**
     * 执行post请求 <br>
     * Created 2014年9月16日 上午12:16:59
     * 
     * @param requestUrl
     *            请求地址
     * @param params
     *            参数
     * @param headerMap
     *            请求头
     * @param content_type
     *            内容类型
     * @param content_encoding
     *            内容编码
     * @return String
     * @throws NdException Exception
     * @author wat.ztag
     */
    public static String post(String requestUrl, JSONArray params,
            HashMap<String, String> headerMap, String content_type, String content_encoding)
            throws NdException {
        return post(requestUrl, params == null ? null : params.toString(), headerMap, content_type,
                content_encoding);
    }

    /**
     * 执行post请求 <br>
     * Created 2014年9月16日 上午12:16:59
     * 
     * @param requestUrl
     *            请求地址
     * @param params
     *            参数
     * @param headerMap
     *            请求头
     * @param content_type
     *            内容类型
     * @param content_encoding
     *            内容编码
     * @return String
     * @throws NdException Exception
     * @author wat.ztag
     */
    public static String post(String requestUrl, String params, HashMap<String, String> headerMap,
            String content_type, String content_encoding) throws NdException {
        Log.d(requestUrl);
        BufferedReader in = null;
        try {
            HttpPost request = new HttpPost(requestUrl);
            HttpParams httpParams = new BasicHttpParams();
            HttpClientParams.setRedirecting(httpParams, true);
            // 请求超时10秒
            int timeoutConnection = n10000;
            HttpConnectionParams.setConnectionTimeout(httpParams, timeoutConnection);
            // socket超时60秒
            int timeoutSocket = n60000;
            HttpConnectionParams.setSoTimeout(httpParams, timeoutSocket);
            HttpClient client = new DefaultHttpClient(httpParams);
            if (headerMap != null) {
                for (String name : headerMap.keySet()) {
                    request.addHeader(name, headerMap.get(name));
                }
            }
            if (params != null) {
                HttpEntity entity;
                StringEntity s = new StringEntity(params, content_encoding);
                Log.d(params);
                s.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, content_type));
                s.setContentEncoding(new BasicHeader(HTTP.CONTENT_ENCODING, content_encoding));
                entity = s;
                request.setEntity(entity);
            }
            HttpResponse response = client.execute(request);
            int responseCode = response.getStatusLine().getStatusCode();
            in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
            StringBuilder sb = new StringBuilder();
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line).append(NL);
            }
            in.close();
            String strResponse = sb.toString();
            Log.d(responseCode + ": " + strResponse);
            JSONObject jsonResult = null;
            JSONObject jsonMeta = null;
            String strData = null;
            if (responseCode == HttpStatus.SC_OK) {
                try {
                    jsonResult = new JSONObject(strResponse);
                    if (jsonResult.has(FIELD_DATA)) {
                        strData = jsonResult.getString(FIELD_DATA);
                    }
                } catch (Exception e) {
                    Log.i(e.toString());
                }
                if (strData != null) {
                    strResponse = strData;
                }
            } else if (responseCode == HttpStatus.SC_UNAUTHORIZED) {
                jsonResult = new JSONObject(strResponse);
                jsonResult.put("code", HttpStatus.SC_UNAUTHORIZED);
                throw new NdException(jsonResult);
            } else {
                try {
                    jsonResult = new JSONObject(strResponse);
                    if (jsonResult.has(FIELD_META)) {
                        jsonMeta = jsonResult.getJSONObject(FIELD_META);
                    }
                } catch (Exception e) {
                    Log.i(e.toString());
                }
                if (jsonMeta != null) {
                    throw new NdException(jsonMeta);
                }
                if (strResponse != null && strResponse.length() > 2) {
                    throw new NdException(responseCode, strResponse);
                } else {
                    throw new NdException(responseCode, getErrorMsg(responseCode));
                }
            }
            return strResponse;
        } catch (SocketException e) {
            // 无网络链接
            throw new NdException(NET_WORK_NOT_ACTIVIE, NET_WORK_NOT_ACTIVIE_DESC);
        } catch (UnknownHostException e) {
            // 无网络链接
            throw new NdException(NET_WORK_NOT_ACTIVIE, NET_WORK_NOT_ACTIVIE_DESC);
        } catch (SocketTimeoutException e) {
            // 连接超时
            throw new NdException(NET_WORK_SOCKET_TIME_OUT, NET_WORK_SOCKET_TIME_OUT_DESC);
        } catch (Exception e) {
            throw new NdException(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 执行delete请求
     * 
     * @param requestUrl
     *            请求地址
     * @return String
     * @throws NdException Exception
     */
    public static String delete(String requestUrl) throws NdException {
        return get(requestUrl, null, CONTENT_TYPE_JSON, CONTENT_ENCODING);
    }

    /**
     * 执行delete请求
     * 
     * @param requestUrl
     *            请求地址
     * @param headerMap
     *            请求头
     * @return String
     * @throws NdException Exception
     */ 
    public static String delete(String requestUrl, HashMap<String, String> headerMap)
            throws NdException {
        return delete(requestUrl, headerMap, CONTENT_TYPE_JSON, CONTENT_ENCODING);
    }

    /**
     * 执行delete请求
     * 
     * @param requestUrl
     *            请求地址
     * @param headerMap
     *            请求头
     * @param content_type
     *            内容类型
     * @param content_encoding
     *            内容编码
     * @return String
     * @throws NdException Exception
     */
    public static String delete(String requestUrl, HashMap<String, String> headerMap,
            String content_type, String content_encoding) throws NdException {
        BufferedReader in = null;
        InputStream is;
        Log.d(requestUrl);
        try {
            HttpParams httpParams = new BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(httpParams, n20000);
            HttpConnectionParams.setSoTimeout(httpParams, n60000);
            HttpClientParams.setRedirecting(httpParams, true);
            HttpClient client = new DefaultHttpClient(httpParams);
            HttpDelete request = new HttpDelete();
            request.setURI(new URI(requestUrl));
            if (headerMap != null) {
                for (String name : headerMap.keySet()) {
                    request.addHeader(name, headerMap.get(name));
                }
            }
            request.addHeader("Accept-Encoding", "gzip");
            HttpResponse response = client.execute(request);
            int responseCode = response.getStatusLine().getStatusCode();
            is = response.getEntity().getContent();
            for (Header header : response.getAllHeaders()) {
                String name = header.getName();
                String value = header.getValue();
                if (name.equals("Content-Encoding") && value.equals("gzip")) {
                    is = new GZIPInputStream(is);
                }
            }
            in = new BufferedReader(new InputStreamReader(is, content_encoding));
            StringBuffer sb = new StringBuffer("");
            String line = "";
            String NL = System.getProperty("line.separator");
            while ((line = in.readLine()) != null) {
                sb.append(line + NL);
            }
            in.close();
            String strResponse = sb.toString();
            Log.d(responseCode + ": " + strResponse);
            JSONObject jsonResult = null;
            JSONObject jsonMeta = null;
            String strData = null;
            if (responseCode == HttpStatus.SC_OK) {
                try {
                    jsonResult = new JSONObject(strResponse);
                    if (jsonResult.has(FIELD_DATA)) {
                        strData = jsonResult.getString(FIELD_DATA);
                    }
                } catch (Exception e) {
                    Log.i(e.toString());
                }
                if (strData != null) {
                    Log.i("strData != null");
                }
                strResponse = strData;
            } else if (responseCode == HttpStatus.SC_UNAUTHORIZED) {
                jsonResult = new JSONObject(strResponse);
                jsonResult.put("code", HttpStatus.SC_UNAUTHORIZED);
                throw new NdException(jsonResult);
            } else {
                try {
                    jsonResult = new JSONObject(strResponse);
                    if (jsonResult.has(FIELD_META)) {
                        jsonMeta = jsonResult.getJSONObject(FIELD_META);
                    }
                } catch (Exception e) {
                    Log.i(e.toString());
                }
                if (jsonMeta != null) {
                    throw new NdException(jsonMeta);
                }
                if (strResponse != null && strResponse.length() > 2) {
                    throw new NdException(responseCode, strResponse);
                } else {
                    throw new NdException(responseCode, getErrorMsg(responseCode));
                }
            }
            return strResponse;
        } catch (SocketException e) {
            // 无网络链接
            throw new NdException(NET_WORK_NOT_ACTIVIE, NET_WORK_NOT_ACTIVIE_DESC);
        } catch (UnknownHostException e) {
            // 无网络链接
            throw new NdException(NET_WORK_NOT_ACTIVIE, NET_WORK_NOT_ACTIVIE_DESC);
        } catch (SocketTimeoutException e) {
            // 连接超时
            throw new NdException(NET_WORK_SOCKET_TIME_OUT, NET_WORK_SOCKET_TIME_OUT_DESC);
        } catch (Exception e) {
            throw new NdException(e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * <br>
     * Created 2014年9月16日 上午12:17:14
     * 
     * @param code int
     * @return String
     * @author wat.ztag
     */
    private static String getErrorMsg(int code) {
        String result = "错误";
        switch (code) {
        case HttpStatus.SC_BAD_REQUEST:
            result = HTTP_STATUS_400;
            break;
        case HttpStatus.SC_UNAUTHORIZED:
            result = HTTP_STATUS_401;
            break;
        case HttpStatus.SC_FORBIDDEN:
            result = HTTP_STATUS_403;
            break;
        case HttpStatus.SC_NOT_FOUND:
            result = HTTP_STATUS_404;
            break;
        case HttpStatus.SC_METHOD_NOT_ALLOWED:
            result = HTTP_STATUS_405;
            break;
        case HttpStatus.SC_NOT_ACCEPTABLE:
            result = HTTP_STATUS_406;
            break;
        case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
            result = HTTP_STATUS_407;
            break;
        case HttpStatus.SC_REQUEST_TIMEOUT:
            result = HTTP_STATUS_408;
            break;
        case HttpStatus.SC_CONFLICT:
            result = HTTP_STATUS_409;
            break;
        default:
            break;
        }
        return result;
    }

    /**
     * 
     * <br>Created 2014年11月28日 上午12:05:46
     * @author       wat.ztag
    */
    @Override
    public void initMagicNumber() {
    }
}
